/*    This file is part of unfy.
 *
 *    Unfy is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU Lesser General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    Unfy is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public License
 *    along with unfy.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef UNFY_H
#define UNFY_H

/*
Include:
something with size_t
#include <rid.h>

#include <unfy/unfy.h>
*/

#ifndef STYLE_9
#include <rid.h>
#endif

typedef enum {
	UNFY_RSN_OKAY,
	UNFY_RSN_VAL,
	UNFY_RSN_TYPE,
	UNFY_RSN_LEN,
	UNFY_RSN_SELF,
	UNFY_RSN_FORM,
} Unfy_rsn;

typedef enum {
	UNFY_CONST = 0,
	UNFY_ORDER,
	UNFY_IGN,
	UNFY_LIST,
	UNFY_VAR,
} Unfy_type;

typedef enum {
	UNFY_YES,
	UNFY_NO,
	UNFY_ERR,
} Unfy_stat;

typedef struct Unfy_list Unfy_list;

typedef struct {
	Unfy_type type;

	union {
		Rid id;
		Unfy_list *list;
		void *dat;
		size_t order;
	} u;
} Unfy_term;

struct Unfy_list {
	Unfy_list *next;
	Unfy_term *term;
};

typedef struct Unfy_bind Unfy_bind;

struct Unfy_bind {
	Unfy_bind *next;
	Rid var_id;
	Unfy_term *term;
};

typedef struct {
	Unfy_term *terms;
	Unfy_list *lists;
	Unfy_bind *binds;
} Unfy_recycle;

typedef struct {
	Unfy_bind *lbind;
	Unfy_bind *rbind;
	Unfy_rsn rsn;
	Unfy_term *left;
	Unfy_term *right;
	Unfy_term *lvar;
	Unfy_term *rvar;
} Unfy_info;

/* recycle */

void
unfy_recycle_init(Unfy_recycle *rec);

void
unfy_recycle_empty(Unfy_recycle *rec);

void
unfy_recycle_term(Unfy_recycle *rec, Unfy_term *term);

void
unfy_recycle_list(Unfy_recycle *rec, Unfy_list *list);

void
unfy_recycle_bind(Unfy_recycle *rec, Unfy_bind *bind);

/* term */

Unfy_term *
unfy_term(Unfy_type type, void *dat, Unfy_recycle *rec);

Unfy_term *
unfy_term_id(Unfy_type type, const Rid id, Unfy_recycle *rec);

Unfy_term *
unfy_term_copy(const Unfy_term *term, Unfy_recycle *rec);

void
unfy_term_init(Unfy_term *term, Unfy_type type, void *dat);

int
unfy_term_init_copy(Unfy_term *des, const Unfy_term *src, Unfy_recycle *rec);

Unfy_stat
unfy_term_same(Unfy_info *info, Unfy_recycle *rec);

int
unfy_term_revar(const Unfy_term *term, Unfy_bind **bind, Unfy_recycle *rec);

/* list */

Unfy_list *
unfy_list(Unfy_term *term, Unfy_list *next, Unfy_recycle *rec);

int
unfy_list_copy(Unfy_list **copy, const Unfy_list *list, Unfy_recycle *rec);

void
unfy_list_init(Unfy_list *list, Unfy_term *term, Unfy_list *next);

int
unfy_list_init_copy(Unfy_list *copy, const Unfy_list *list, Unfy_recycle *rec);

Unfy_stat
unfy_list_same(Unfy_info *info, Unfy_list *llist, Unfy_list *rlist,
	       Unfy_recycle *rec);

Unfy_list **
unfy_list_append(Unfy_list **tail, Unfy_term *term, Unfy_recycle *rec);

/* binding */

int
unfy_bind(Unfy_bind **bind, const Rid var_id, Unfy_term *term,
	  Unfy_recycle *rec);

Unfy_bind *
unfy_bind_copy(const Unfy_bind *bind, Unfy_recycle *rec);

Unfy_term *
unfy_bind_get(const Unfy_bind *bind, const Rid var_id);

Unfy_stat
unfy_bind_replace(Unfy_bind *bind, const Rid var_id, const Unfy_term *val,
		  Unfy_recycle *rec);

Unfy_term *
unfy_term_bind(const Unfy_term *term, const Unfy_bind *bind, Unfy_recycle *rec);

int
unfy_term_bind_set(Unfy_term *term, const Unfy_bind *bind, Unfy_recycle *rec);

/* unification */

void
unfy_info_init(Unfy_info *info, Unfy_term *left, Unfy_term *right);

void
unfy_info_dispose(Unfy_info *info, Unfy_recycle *rec);

Unfy_stat
unfy_unify(Unfy_info *info, Unfy_recycle *rec);

#endif
